package com.ccit.paas.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ccit.wf.dto.request.FlowAppointNodeApproverDTO;
import com.ccit.wf.dto.request.FlowAssignTaskReqDTO;
import com.ccit.wf.dto.request.FlowDanglingTaskReqDTO;
import com.ccit.wf.dto.request.FlowEndingTaskReqDTO;
import com.ccit.wf.dto.request.FlowLoadActionPermissionsReqDTO;
import com.ccit.wf.dto.request.FlowLoadRollbackNodeInfoReqDTO;
import com.ccit.wf.dto.request.FlowLoadTaskReqDTO;
import com.ccit.wf.dto.request.FlowMultiReqDTO;
import com.ccit.wf.dto.request.FlowPreviewReqDTO;
import com.ccit.wf.dto.request.FlowQueryApprovalReqDTO;
import com.ccit.wf.dto.request.FlowQueryReqDTO;
import com.ccit.wf.dto.request.FlowRemindTaskTaskReqDTO;
import com.ccit.wf.dto.request.FlowResetTaskReqDTO;
import com.ccit.wf.dto.request.FlowResumeTaskReqDTO;
import com.ccit.wf.dto.request.FlowRetakeTaskReqDTO;
import com.ccit.wf.dto.request.FlowRollBackTaskReqDTO;
import com.ccit.wf.dto.request.FlowSingleReqDTO;
import com.ccit.wf.dto.request.FlowStartTaskReqDTO;
import com.ccit.wf.dto.request.FlowSubmitTaskReqDTO;
import com.ccit.wf.dto.request.FlowSuspendTaskTaskReqDTO;
import com.ccit.wf.dto.request.FlowTakeTaskReqDTO;
import com.ccit.wf.dto.request.JointReviewTaskReqDTO;
import com.ccit.wf.dto.request.NodeApproveInfoDTO;
import com.ccit.wf.dto.request.SimulateFlowRequestDTO;
import com.ccit.wf.dto.request.base.BillExtendPropReqDTO;
import com.ccit.wf.dto.request.base.FlowBizParamBaseReqDTO;
import com.ccit.wf.dto.request.base.NodeApproverInfoReqDTO;
import com.ccit.wf.dto.request.base.NodeInfoDto;
import com.ccit.wf.dto.request.base.PositionUserInfoDTO;
import com.ccit.wf.dto.request.base.UserInfoDTO;
import com.ccit.wf.dto.response.FlowApprovalInfoDTO;
import com.ccit.wf.dto.response.FlowDanglingTaskRespDTO;
import com.ccit.wf.dto.response.FlowEndingTaskRespDTO;
import com.ccit.wf.dto.response.FlowLoadActionPermissionsRespDTO;
import com.ccit.wf.dto.response.FlowLoadRollBackNodeInfoRespDTO;
import com.ccit.wf.dto.response.FlowLoadTaskRespDTO;
import com.ccit.wf.dto.response.FlowQueryApprovalStepsRespDTO;
import com.ccit.wf.dto.response.FlowQueryRespDTO;
import com.ccit.wf.dto.response.FlowResetTaskRespDTO;
import com.ccit.wf.dto.response.FlowRetakeTaskRespDTO;
import com.ccit.wf.dto.response.FlowRollBackTaskRespDTO;
import com.ccit.wf.dto.response.FlowStartTaskRespDTO;
import com.ccit.wf.dto.response.FlowSubmitTaskRespDTO;
import com.ccit.wf.dto.response.JointReviewTaskRespDTO;
import com.ccit.wf.dto.response.LoadFlowListRespDTO;
import com.ccit.wf.dto.response.SimulateFlowResponseDTO;
import com.ccit.wf.util.WorkFlowRepositoryService;
import com.ccit.wf.util.WorkFlowRuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.crypto.Data;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

@RestController
@RequestMapping("/workflow")
public class WorkflowController {
    private static JSONObject jsonObject = new JSONObject();
    private static final String USER_ID = "1402327";
    private static final String USERNAME = "杨思豪";
    @Autowired
    private WorkFlowRuntimeService workFlowRuntimeService;
    @Autowired
    private WorkFlowRepositoryService workFlowRepositoryService;

    @RequestMapping("/startTask")
    public FlowStartTaskRespDTO startTask(String flowId, String sysId, String bizTitle, int isSubmitAfterStart, String bizNo, String orgId, String orgTreeId, @RequestParam(required = false) String jsonParam) {
        FlowSingleReqDTO flowSingleReqDTO = new FlowSingleReqDTO();
        FlowStartTaskReqDTO flowStartTaskReqDTO = new FlowStartTaskReqDTO();
        flowStartTaskReqDTO.setFlowId(flowId);
        flowStartTaskReqDTO.setSysId(sysId);
        flowStartTaskReqDTO.setBizNo(bizNo);
        flowStartTaskReqDTO.setBizTitle(bizTitle);
        flowStartTaskReqDTO.setSubmitAfterStart(String.valueOf(isSubmitAfterStart));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("bizDate", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        jsonObject.put("bizOrgId", orgId);
        jsonObject.put("bizOrgTreeId", orgTreeId);
        /*JSONObject param = JSONObject.parseObject(jsonParam);
        for (String key : param.keySet()) {
            jsonObject.put(key, param.get(key));
        }*/
        flowStartTaskReqDTO.setVariableData(jsonObject);
        /*BillExtendPropReqDTO dto = new BillExtendPropReqDTO();
        dto.setEXT_STR01("测试扩展字段");
        dto.setEXT_STR02("测试扩展字段2");
        flowStartTaskReqDTO.setExtProp(dto);*/

        //测试开启流程替换节点审批人
        /*NodeApproverInfoReqDTO dto = new NodeApproverInfoReqDTO();
        dto.setFlowId("process_1");
        dto.setNodeId("S_1");
        dto.setApprovalType("ParaMultSign");
        ArrayList<UserInfoDTO> userInfos = new ArrayList<>();

        UserInfoDTO userInfo1 = new UserInfoDTO();
        userInfo1.setPositionId("CSGW");
        userInfo1.setPositionName("测试岗位");
        PositionUserInfoDTO user1 = new PositionUserInfoDTO();
        user1.setUserId("10413709");
        user1.setUserName("吕金锐");
        userInfo1.setPositionUserInfos(List.of(user1));

        UserInfoDTO userInfo5 = new UserInfoDTO();
        userInfo5.setPositionId("CSGW");
        userInfo5.setPositionName("测试岗位");
        PositionUserInfoDTO user5 = new PositionUserInfoDTO();
        user5.setUserId("10413698");
        user5.setUserName("李艳敏");
        userInfo5.setPositionUserInfos(List.of(user5));

        UserInfoDTO userInfo2 = new UserInfoDTO();
        userInfo2.setPositionId("CSGW2");
        userInfo2.setPositionName("测试岗位2");
        PositionUserInfoDTO user2 = new PositionUserInfoDTO();
        user2.setUserId("10413696");
        user2.setUserName("董琴");
        userInfo2.setPositionUserInfos(List.of(user2));

        UserInfoDTO userInfo3 = new UserInfoDTO();
        userInfo3.setPositionId("CSGW3");
        userInfo3.setPositionName("测试岗位3");
        PositionUserInfoDTO user4 = new PositionUserInfoDTO();
        user4.setUserId("10413697");
        user4.setUserName("韩雪荣");
        userInfo3.setPositionUserInfos(List.of(user4));

        userInfos.add(userInfo1);
        userInfos.add(userInfo2);
        userInfos.add(userInfo3);
        userInfos.add(userInfo5);
        dto.setUserInfo(userInfos);
        flowStartTaskReqDTO.setNodeApproverInfos(Arrays.asList(dto));*/

        flowSingleReqDTO.setBizParam(flowStartTaskReqDTO);
        flowSingleReqDTO.setUserId(USER_ID);
        flowSingleReqDTO.setUserName(USERNAME);
        flowSingleReqDTO.setTimestamp(System.currentTimeMillis());
        return processRequest(flowSingleReqDTO, workFlowRuntimeService::startTask);
    }

    @RequestMapping("/endingTask")
    public FlowEndingTaskRespDTO endingTask(String taskId, String instanceId, String userId, String userName) {
        FlowMultiReqDTO<FlowEndingTaskReqDTO> flowEndingTaskReqDTOFlowMultiReqDTO = new FlowMultiReqDTO<>();
        FlowEndingTaskReqDTO endingTaskReqDTO = new FlowEndingTaskReqDTO();
        endingTaskReqDTO.setTaskId(taskId);
        endingTaskReqDTO.setOpinion("测试作废");
        endingTaskReqDTO.setInstanceId(instanceId);
        List<FlowEndingTaskReqDTO> list = new ArrayList<>();
        list.add(endingTaskReqDTO);
        flowEndingTaskReqDTOFlowMultiReqDTO.setBizParam(list);
        flowEndingTaskReqDTOFlowMultiReqDTO.setUserId(userId);
        flowEndingTaskReqDTOFlowMultiReqDTO.setUserName(userName);
        return processRequest(flowEndingTaskReqDTOFlowMultiReqDTO, workFlowRuntimeService::endingTask);
    }

    @RequestMapping("/submitTask")
    public FlowSubmitTaskRespDTO submitTask(String taskId, String instanceId, String flowId, String nodeId, String approvalType, String userId, String userName) {
        FlowMultiReqDTO<FlowSubmitTaskReqDTO> flowSubmitTaskReqDTOFlowMultiReqDTO = new FlowMultiReqDTO<>();
        FlowSubmitTaskReqDTO flowSubmitTaskReqDTO = new FlowSubmitTaskReqDTO();
        flowSubmitTaskReqDTO.setTaskId(taskId);
        flowSubmitTaskReqDTO.setOpinion("批准");
        flowSubmitTaskReqDTO.setInstanceId(instanceId);

        /*NodeApproveInfoDTO dto = new NodeApproveInfoDTO();
        dto.setFlowId("process_1");
        dto.setNodeId("S_2");
        FlowApprovalInfoDTO userInfo1 = new FlowApprovalInfoDTO();
        userInfo1.setUserId("10313336");
        userInfo1.setUserName("王雪鹏");
        dto.setUserInfo(Arrays.asList(userInfo1));*/

        NodeApproveInfoDTO dto2 = new NodeApproveInfoDTO();
        dto2.setFlowId("process_8");
        dto2.setNodeId("S_3");
        FlowApprovalInfoDTO userInfo2 = new FlowApprovalInfoDTO();
        userInfo2.setUserId("10413698");
        userInfo2.setUserName("李艳敏");
        dto2.setUserInfo(Arrays.asList(userInfo2));

        flowSubmitTaskReqDTO.setNodeApproverInfos(Arrays.asList(dto2));

        JSONObject js = new JSONObject();
        js.put("bizJe", 23223);
        js.put("flowId", flowId);
        js.put("nodeId", nodeId);
        js.put("userInfo.userId", USER_ID);
        js.put("userInfo.userName", USERNAME);
        js.put("approvalType", approvalType);

        //测试指定节点提交
        /*js.put("taskId", taskId);
        js.put("instanceId", instanceId);
        js.put("opinion", "指定节点提交");
        js.put("submitToFlowId", flowId);
        js.put("submitToNodeId", nodeId);
        flowSubmitTaskReqDTO.setVariableData(js);*/

        List<FlowSubmitTaskReqDTO> list = new ArrayList<>();
        list.add(flowSubmitTaskReqDTO);
        flowSubmitTaskReqDTOFlowMultiReqDTO.setBizParam(list);
        flowSubmitTaskReqDTOFlowMultiReqDTO.setUserId(userId);
        flowSubmitTaskReqDTOFlowMultiReqDTO.setUserName(userName);
        return processRequest(flowSubmitTaskReqDTOFlowMultiReqDTO, workFlowRuntimeService::submitTask);
    }

    @RequestMapping("/retakeTask")
    public FlowRetakeTaskRespDTO retakeTask(String taskId, String instanceId, String userId, String userName) {
        FlowMultiReqDTO<FlowRetakeTaskReqDTO> flowRetakeTaskReqDTOFlowMultiReqDTO = new FlowMultiReqDTO<>();
        FlowRetakeTaskReqDTO retakeTaskRespDTO = new FlowRetakeTaskReqDTO();
        retakeTaskRespDTO.setTaskId(taskId);
        retakeTaskRespDTO.setOpinion("取回");
        retakeTaskRespDTO.setInstanceId(instanceId);
        List<FlowRetakeTaskReqDTO> list = new ArrayList<>();
        list.add(retakeTaskRespDTO);
        flowRetakeTaskReqDTOFlowMultiReqDTO.setBizParam(list);
        flowRetakeTaskReqDTOFlowMultiReqDTO.setUserId(userId);
        flowRetakeTaskReqDTOFlowMultiReqDTO.setUserName(userName);
        return processRequest(flowRetakeTaskReqDTOFlowMultiReqDTO, workFlowRuntimeService::retakeTask);
    }

    @RequestMapping("/loadRollbackToFlowNode")
    public FlowLoadRollBackNodeInfoRespDTO loadRollbackToFlowNodeInfo(String instanceId) {
        FlowSingleReqDTO<FlowLoadRollbackNodeInfoReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowLoadRollbackNodeInfoReqDTO reqDTO = new FlowLoadRollbackNodeInfoReqDTO();
        reqDTO.setInstanceId(instanceId);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(USER_ID);
        flowParamDTO.setUserName(USERNAME);
        System.out.println(JSON.toJSONString(flowParamDTO));
        return processRequest(flowParamDTO, workFlowRepositoryService::loadRollbackToFlowNodeInfo);
    }

    @RequestMapping("/rollbackTask")
    public FlowRollBackTaskRespDTO rollbackTask(String taskId, String instanceId, String flowId, String nodeId, String rollbackResubmitType, String rollbackToApproverType, String userId, String userName) {
        FlowMultiReqDTO<FlowRollBackTaskReqDTO> flowRollBackTaskReqDTOFlowMultiReqDTO = new FlowMultiReqDTO<>();
        FlowRollBackTaskReqDTO rollBackTaskRespDTO = new FlowRollBackTaskReqDTO();
        rollBackTaskRespDTO.setTaskId(taskId);
        rollBackTaskRespDTO.setOpinion(userName + ":驳回");
        rollBackTaskRespDTO.setInstanceId(instanceId);
        rollBackTaskRespDTO.setRollbackToFlowId(flowId);
        rollBackTaskRespDTO.setRollbackToNodeId(nodeId);
        rollBackTaskRespDTO.setRollbackResubmitType(rollbackResubmitType);
        rollBackTaskRespDTO.setRollbackToApproverType(rollbackToApproverType);
        List<FlowRollBackTaskReqDTO> list = new ArrayList<>();
        list.add(rollBackTaskRespDTO);
        flowRollBackTaskReqDTOFlowMultiReqDTO.setBizParam(list);
        flowRollBackTaskReqDTOFlowMultiReqDTO.setUserId(userId);
        flowRollBackTaskReqDTOFlowMultiReqDTO.setUserName(userName);
        return processRequest(flowRollBackTaskReqDTOFlowMultiReqDTO, workFlowRuntimeService::rollbackTask);
    }


    @RequestMapping("/resetTask")
    public FlowResetTaskRespDTO resetTask(String taskId, String instanceId, String userId, String userName) {
        FlowMultiReqDTO<FlowResetTaskReqDTO> flowResetTaskReqDTOFlowMultiReqDTO = new FlowMultiReqDTO<>();
        FlowResetTaskReqDTO resetTaskReqDTO = new FlowResetTaskReqDTO();
        resetTaskReqDTO.setTaskId(taskId);
        resetTaskReqDTO.setOpinion("重置");
        resetTaskReqDTO.setInstanceId(instanceId);
        List<FlowResetTaskReqDTO> list = new ArrayList<>();
        list.add(resetTaskReqDTO);
        flowResetTaskReqDTOFlowMultiReqDTO.setBizParam(list);
        flowResetTaskReqDTOFlowMultiReqDTO.setUserId(userId);
        flowResetTaskReqDTOFlowMultiReqDTO.setUserName(userName);
        return processRequest(flowResetTaskReqDTOFlowMultiReqDTO, workFlowRuntimeService::resetTask);
    }

    @RequestMapping("/assignTask")
    public void assignTask(String taskId, String instanceId, int assignType, String assignToUserId, String assignToUserName, String assignApprovalType, String nodeName, String userId, String userName) {
        FlowSingleReqDTO<FlowAssignTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowAssignTaskReqDTO reqDTO = new FlowAssignTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setOpinion("加签");
        reqDTO.setInstanceId(instanceId);
        reqDTO.setAssignType(String.valueOf(assignType));
        reqDTO.setAssignToUserId(assignToUserId);
        reqDTO.setAssignToUserName(assignToUserName);
        NodeInfoDto dto = new NodeInfoDto();
        dto.setNodeName(nodeName);
        reqDTO.setNodeInfo(dto);
        reqDTO.setAssignApprovalType(assignApprovalType);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::assignTask);
    }

    @RequestMapping("/takeTask")
    public void takeTask(String taskId, String instanceId, String takeUserId, String takeUserName, String userId, String userName) {
        FlowSingleReqDTO<FlowTakeTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowTakeTaskReqDTO reqDTO = new FlowTakeTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setOpinion("转签");
        reqDTO.setInstanceId(instanceId);
        reqDTO.setTakeUserId(takeUserId);
        reqDTO.setTakeUserName(takeUserName);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::takeTask);
    }

    @RequestMapping("/loadFlowTask")
    public FlowLoadTaskRespDTO loadFlowTask(@RequestParam(required = false) String bizNo, String taskType, int pageNo, int pageSize, @RequestParam(required = false) String loadAllMyBill, String userId, String userName) {
        FlowSingleReqDTO<FlowLoadTaskReqDTO> flowParamDTO = new FlowSingleReqDTO();
        FlowLoadTaskReqDTO reqDTO = new FlowLoadTaskReqDTO();
        reqDTO.setBizNo(bizNo);
        reqDTO.setEndTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        reqDTO.setStartTime("1970-1-1 00:00:00");
        reqDTO.setIsPaging("1");
        reqDTO.setTaskType(taskType);
        reqDTO.setYwsy("");
        reqDTO.setPageNo(pageNo);
        reqDTO.setPageSize(pageSize);
        reqDTO.setLoadAllMyBill(loadAllMyBill);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::loadFlowTask);
    }

    @RequestMapping("/loadActionPermissionsInfo")
    public FlowLoadActionPermissionsRespDTO loadActionPermissionsInfo(String flowId, String nodeId, String userId, String userName) {
        FlowSingleReqDTO<FlowLoadActionPermissionsReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowLoadActionPermissionsReqDTO reqDTO = new FlowLoadActionPermissionsReqDTO();
        reqDTO.setFlowId(flowId);
        reqDTO.setNodeId(nodeId);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::loadActionPermissionsInfo);
    }

    @RequestMapping("/queryFlowDiagramAndTaskData")
    public FlowQueryApprovalStepsRespDTO queryFlowDiagramAndTaskData(String instanceId, String bizDate, String userId, String userName) {
        FlowSingleReqDTO<FlowQueryApprovalReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowQueryApprovalReqDTO reqDTO = new FlowQueryApprovalReqDTO();
        reqDTO.setInstanceId(instanceId);
        reqDTO.setBizDate(bizDate);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::queryFlowDiagramAndTaskData);
    }

    @RequestMapping("/queryFlowApprovalTrack")
    public FlowQueryApprovalStepsRespDTO queryFlowApprovalTrack(String instanceId, String bizDate, String userId, String userName) {
        FlowSingleReqDTO<FlowQueryApprovalReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowQueryApprovalReqDTO reqDTO = new FlowQueryApprovalReqDTO();
        reqDTO.setInstanceId(instanceId);
        reqDTO.setBizDate(bizDate);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::queryFlowApprovalTrack);
    }

    @RequestMapping("/queryFlowOperationList")
    public FlowQueryRespDTO queryFlowOperationList(String instanceId, String bizDate, String sort, String userId, String userName) {
        FlowSingleReqDTO<FlowQueryReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowQueryReqDTO reqDTO = new FlowQueryReqDTO();
        reqDTO.setInstanceId(instanceId);
        reqDTO.setBizDate(bizDate);
        reqDTO.setSort(sort);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::queryFlowOperationList);
    }

    @RequestMapping("/suspendTask")
    public void suspendTask(String taskId, String instanceId, String userId, String userName) {
        FlowSingleReqDTO<FlowSuspendTaskTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowSuspendTaskTaskReqDTO reqDTO = new FlowSuspendTaskTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setInstanceId(instanceId);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::suspendTask);
    }

    @RequestMapping("/resumeTask")
    public void resumeTask(String taskId, String instanceId, String userId, String userName) {
        FlowSingleReqDTO<FlowResumeTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowResumeTaskReqDTO reqDTO = new FlowResumeTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setInstanceId(instanceId);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::resumeTask);
    }

    @RequestMapping("/danglingTask")
    public FlowDanglingTaskRespDTO danglingTask(String taskId, String instanceId, String userId, String userName) {
        FlowSingleReqDTO<FlowDanglingTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowDanglingTaskReqDTO reqDTO = new FlowDanglingTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setInstanceId(instanceId);
        reqDTO.setOpinion("流程悬挂");
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        return processRequest(flowSingleReqDTO, workFlowRuntimeService::danglingTask);
    }

    @RequestMapping("/remindTask")
    public void remindTask(String instanceId, String userId, String userName) {
        FlowSingleReqDTO<FlowRemindTaskTaskReqDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowRemindTaskTaskReqDTO reqDTO = new FlowRemindTaskTaskReqDTO();
        reqDTO.setInstanceId(instanceId);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::remindTask);
    }

    @RequestMapping("/queryFlowApprovalSteps")
    public FlowQueryApprovalStepsRespDTO queryFlowApprovalSteps(String instanceId) {
        FlowSingleReqDTO<FlowQueryApprovalReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowQueryApprovalReqDTO reqDTO = new FlowQueryApprovalReqDTO();
        reqDTO.setInstanceId(instanceId);
        reqDTO.setBizDate("2025");
        flowParamDTO.setUserId(USER_ID);
        flowParamDTO.setUserName(USERNAME);
        flowParamDTO.setBizParam(reqDTO);
        return processRequest(flowParamDTO, workFlowRepositoryService::queryFlowApprovalSteps);
    }

    @RequestMapping("/previewFlow")
    public FlowQueryApprovalStepsRespDTO previewFlow(String flowId, String sysId, String orgId, String orgTreeId, String nodeId, String approvalType, String toUserId, String toUserName, String userId, String userName) {
        FlowSingleReqDTO<FlowPreviewReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        FlowPreviewReqDTO reqDTO = new FlowPreviewReqDTO();
        reqDTO.setFlowId(flowId);
        reqDTO.setSysId(sysId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("bizOrgId", orgId);
        jsonObject.put("bizOrgTreeId", orgTreeId);
        jsonObject.put("str", "BUSI_TYPE_B");
        reqDTO.setVariableData(jsonObject);
        List<NodeApproverInfoReqDTO> list = new ArrayList<>();
        NodeApproverInfoReqDTO nodeApproverInfoReqDTO = new NodeApproverInfoReqDTO();
        nodeApproverInfoReqDTO.setFlowId(flowId);
        nodeApproverInfoReqDTO.setNodeId(nodeId);
        nodeApproverInfoReqDTO.setApprovalType(approvalType);
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUserId(toUserId);
        userInfoDTO.setUserName(toUserName);
        nodeApproverInfoReqDTO.setUserInfo(Arrays.asList(userInfoDTO));
        reqDTO.setNodeApproverInfos(list);
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRepositoryService::previewFlow);
    }

    @RequestMapping("/appointNodeApprover")
    public void appointNodeApprover(String instanceId, String flowId, String nodeId, String approvalType, String toUserId, String toUserName, String userId, String userName) {
        FlowSingleReqDTO<FlowAppointNodeApproverDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        FlowAppointNodeApproverDTO reqDTO = new FlowAppointNodeApproverDTO();
        reqDTO.setInstanceId(instanceId);
        List<NodeApproverInfoReqDTO> list = new ArrayList<>();
        NodeApproverInfoReqDTO nodeApproverInfoReqDTO = new NodeApproverInfoReqDTO();
        nodeApproverInfoReqDTO.setFlowId(flowId);
        nodeApproverInfoReqDTO.setNodeId(nodeId);
        nodeApproverInfoReqDTO.setApprovalType(approvalType);
        List<UserInfoDTO> userInfo = new ArrayList<>();
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUserName(toUserName);
        userInfoDTO.setUserId(toUserId);
        userInfo.add(userInfoDTO);
        nodeApproverInfoReqDTO.setUserInfo(userInfo);
        list.add(nodeApproverInfoReqDTO);
        reqDTO.setNodeApproverInfos(list);
        flowSingleReqDTO.setBizParam(reqDTO);
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        processRequest(flowSingleReqDTO, workFlowRuntimeService::appointNodeApprover);
    }

    @RequestMapping("/jointReviewTask")
    public JointReviewTaskRespDTO jointReviewTask(String taskId, String instanceId, String jointReviewToUserId, String jointReviewToUserName, String userId, String userName) {
        JointReviewTaskReqDTO reqDTO = new JointReviewTaskReqDTO();
        reqDTO.setTaskId(taskId);
        reqDTO.setInstanceId(instanceId);
        reqDTO.setJointReviewToUserId(jointReviewToUserId);
        reqDTO.setJointReviewToUserName(jointReviewToUserName);
        reqDTO.setOpinion("发起协审");
        FlowSingleReqDTO<JointReviewTaskReqDTO> flowParamDTO = new FlowSingleReqDTO<>();
        flowParamDTO.setBizParam(reqDTO);
        flowParamDTO.setUserId(userId);
        flowParamDTO.setUserName(userName);
        return processRequest(flowParamDTO, workFlowRuntimeService::jointReviewTask);
    }

    @RequestMapping("/simulateFlow")
    public SimulateFlowResponseDTO simulateFlow(String flowId, String nodeId, String sysId, String bizOrgId, String bizOrgTreeId, String userId, String userName) {
        FlowSingleReqDTO<SimulateFlowRequestDTO> flowSingleReqDTO = new FlowSingleReqDTO<>();
        SimulateFlowRequestDTO dto = new SimulateFlowRequestDTO();
        dto.setFlowId(flowId);
        dto.setNodeId(nodeId);
        dto.setSysId(sysId);
        JSONObject json = new JSONObject();
        json.put("bizOrgId", bizOrgId);
        json.put("bizOrgTreeId", bizOrgTreeId);
        json.put("bizDate", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        dto.setVariableData(json);
        flowSingleReqDTO.setBizParam(dto);
        flowSingleReqDTO.setTimestamp(System.currentTimeMillis());
        flowSingleReqDTO.setUserId(userId);
        flowSingleReqDTO.setUserName(userName);
        return processRequest(flowSingleReqDTO, workFlowRepositoryService::simulateFlow);
    }


    public static <T, R> R processRequest(T request, Function<T, R> function) {
        System.err.println(jsonObject.toJSONString(request));
        R response = function.apply(request);
        return response;
    }

    public static <T> void processRequest(T request, Consumer<T> function) {
        System.err.println(jsonObject.toJSONString(request));
        function.accept(request);
    }
}
